use color_eyre::{eyre::eyre, Result};
use tracing::{error, info, instrument};
use tracing::{event, span, Level};
use tracing_appender::{non_blocking, rolling};
use tracing_error::ErrorLayer;
use tracing_subscriber::{
    filter::EnvFilter, fmt, layer::SubscriberExt, util::SubscriberInitExt, Registry,
};

#[instrument]
fn return_err() -> Result<()> {
    Err(eyre!("Something went wrong"))
}

#[instrument]
fn call_return_err() {
    info!("going to log error");
    if let Err(err) = return_err() {
        // 推荐大家运行下，看看这里的输出效果
        error!(?err, "error");
    }
}

#[instrument]
fn my_function(my_arg: usize) {
    event!(Level::INFO, "inside my_function:{my_arg}!");
}

#[derive(Debug)]
struct MyStruct {
    field: &'static str,
}

fn main() -> Result<()> {
    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
    let formatting_layer = fmt::layer().with_file(false).with_writer(std::io::stdout);

    let file_appender = rolling::never("logs", "app.log");
    let (non_blocking_appender, _guard) = non_blocking(file_appender);
    let file_layer = fmt::layer()
        .with_ansi(false)
        .with_writer(non_blocking_appender);

    Registry::default()
        .with(env_filter)
        .with(ErrorLayer::default())
        .with(formatting_layer)
        .with(file_layer)
        .init();

    let my_struct = MyStruct {
        field: "Hello world!",
    };
    let user = "ferris";
    let email = "ferris@rust-lang.org";
    event!(Level::INFO, user, user.email = email, "something happedned");
    event!(Level::INFO, greeting = ?my_struct);

    let span = span!(Level::TRACE, "my_span");
    let _guard = span.enter();

    event!(Level::DEBUG, "something happened inside my_span");

    Ok(())
}
